<?php

class TypesImporter implements iTypesImporter {
	
	private
		$filename = '',
		$validate = false,
		$xml = null,
		$aVaitConnectedFields = array(),
		$aVaitGuidesFields = array(),
		$aVaitImagesFields = array();
	
	public function __construct($filename) {
		$this->filename = $filename;
	}
	
	public function validate() {
		$typesController = TypesController::getInstance();
		
		$this->xml = new DOMDocument;
		if (!$this->xml->load($this->filename, LIBXML_NOERROR)) {
			return array(lang('error_validate_load_xml',__CLASS__));
		}
		
		$aErrors = array();
				
		$aAllTypes = array();
		
		$oExplayType = $typesController->getTypeByName('explay_type');
		
		$sel = new Selection;
		$sel->addType($oExplayType);
		
		$res = $sel->getList();
		
		foreach ($res as $row) {
			$oType = $typesController->getTypeById($row[0]);
			$aAllTypes[$oType->getName()] = $oType->getRealFieldsNames();
		}
		
		$importType = $this->xml->getElementsByTagName('import-types')->item(0)->getElementsByTagName('type');
		
		for ($i = 0; $i < $importType->length; ++$i) {
			$type = $importType->item(0);
			$typeName = $type->getAttribute('name');
			
			if (isset($aAllTypes[$typeName])) {
				$aErrors[] = lang('error_validate_type_exists',__CLASS__) . $typeName;
			}
			
			$aFields = array();
			
			$field = $type->getElementsByTagName('field');
			
			for ($i = 0; $i < $field->length; ++$i) {
				$aFields[] = $field->item($i)->nodeValue;
			}

			$aAllTypes[$typeName] = $aFields;
		}
		
		$requiredType = $this->xml->getElementsByTagName('required-types')->item(0)->getElementsByTagName('type');
		
		for ($i = 0; $i < $requiredType->length; ++$i) {
			$type = $requiredType->item($i);
			$typeName = $type->getAttribute('name');
			
			if (!isset($aAllTypes[$typeName])) {
				$aErrors[] = lang('error_validate_type_not_exists',__CLASS__) . $typeName;
			}
			
			$field = $type->getElementsByTagName('field');
			
			for ($i = 0; $i < $field->length; ++$i) {
				$fieldName = $field->item($i)->nodeValue;
				
				if (!in_array($fieldName, $aAllTypes[$typeName])) {
					$aErrors[] = lang('error_validate_field_not_exists',__CLASS__) . $typeName . '-&gt;' . $fieldName;
				}
			}
		}
		
		if (!count($aErrors)) {
			$this->validate = true;
		}
		
		return $aErrors;
	}
	
	public function import() {
		if (!$this->validate) {
			throw new CoreException(lang('error_not_validate',__CLASS__));
		}
		
		$datatypesNode = $this->xml->getElementsByTagName('datatypes')->item(0);
		
		$typeNode = $datatypesNode->getElementsByTagName('types')->item(0)->getElementsByTagName('type');
		
		$db = DBController::getInstance();
		$db->query("/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */");
		$db->query("/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */");
		
		for ($i = 0; $i < $typeNode->length; ++$i) {
			$this->importType ($typeNode->item($i));
		}
		
		$typesConnection = $datatypesNode->getElementsByTagName('types-connections')->item(0)->getElementsByTagName('connection');
		
		for ($i = 0; $i < $typesConnection->length; ++$i) {
			$this->importTypesConnection($typesConnection->item($i));
		}
		
		$imageProfile = $datatypesNode->getElementsByTagName('images-profiles')->item(0)->getElementsByTagName('image-profile');
		
		for ($i = 0; $i < $imageProfile->length; ++$i) {
			$this->importImageProfile($imageProfile->item($i));
		}
		
		$guide = $datatypesNode->getElementsByTagName('guides')->item(0)->getElementsByTagName('type');
		
		for ($i = 0; $i < $guide->length; ++$i) {
			$this->importGuide($guide->item($i));
		}
		
		$db->query("/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */");
		$db->query("/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;");
	}
	
	private function importType(DOMElement $type) {
		$oType = TypesController::getInstance()->getTypeByName('explay_type');
		
		$properties = $type->getElementsByTagName('properties')->item(0);
		
		$object = new Object($oType);
		$object->setValues(array(
			'name' => $type->getAttribute('name'),
			'title' => $properties->getElementsByTagName('title')->item(0)->nodeValue,
			'table_name' => $properties->getElementsByTagName('table-name')->item(0)->nodeValue,
			'locked' => 0,
			'parent_id' => $properties->getElementsByTagName('parent-id')->item(0)->nodeValue
		));
		$object->createNew();
		
		$typeId = $object->getId();
		
		DBController::getInstance()->query($properties->getElementsByTagName('create-table')->item(0)->nodeValue);
		
		$field = $type->getElementsByTagName('fields')->item(0)->getElementsByTagName('field');
		
		for ($i = 0; $i < $field->length; ++$i) {
			$this->importField($field->item($i), $typeId);
		}
	}
	
	private function importField(DOMElement $field, $typeId) {
		$oTypeField = TypesController::getInstance()->getTypeByName('explay_field');
		
		$character = $field->getElementsByTagName('character')->item(0)->nodeValue;
		
		$maxlength = $field->getElementsByTagName('maxlength')->item(0)->nodeValue;
		
		$object = new Object($oTypeField);
		$object->setValues(array(
			'type_id' => $typeId,
			'field_name' => $field->getAttribute('name'),
			'required' => $field->getElementsByTagName('required')->item(0)->nodeValue,
			'locked' => 0,
			'title' => $field->getElementsByTagName('title')->item(0)->nodeValue,
			'character' => $character,
			'editable' => $field->getElementsByTagName('editable')->item(0)->nodeValue,
			'additional_id' => 0,
			'help' => $field->getElementsByTagName('help')->item(0)->nodeValue,
			'error' => $field->getElementsByTagName('error')->item(0)->nodeValue,
			'position' => $field->getElementsByTagName('position')->item(0)->nodeValue,
			'allow_search' => $field->getElementsByTagName('allow-search')->item(0)->nodeValue,
			'connection_id' => 0
		));
		
		if ($maxlength != '') {
			$object->setValue('maxlength', $maxlength);
		}
		
		if ($character == 'object_value') {
			$key = $field->getElementsByTagName('connection-key')->item(0)->nodeValue;
			$object->setAttribute('connected_field_name', $field->getElementsByTagName('connected-field')->item(0)->nodeValue);
			$this->aVaitConnectedFields[$key][] = $object;
		}
		elseif ($character == 'guide' || $character == 'multiguide') {
			$guideTypeName = $field->getElementsByTagName('guide-type')->item(0)->nodeValue;
			$this->aVaitGuidesFields[$guideTypeName][] = $object;
		}
		elseif ($character == 'image') {
			$key = $field->getElementsByTagName('image-profile')->item(0)->nodeValue;
			$this->aVaitImagesFields[$key][] = $object;
		}
		else {
			$object->createNew();
		}
	}
	
	private function importTypesConnection(DOMElement $typesConnection) {
		$typesController = TypesController::getInstance();
		$fieldsController = FieldsController::getInstance();
		
		$key = $typesConnection->getAttribute('key');
		
		$oTypeConnection = $typesController->getTypeByName('explay_types_connection');
		
		$parentTypeName = $typesConnection->getElementsByTagName('parent-type')->item(0)->nodeValue;
		$parentFieldName = $typesConnection->getElementsByTagName('parent-field')->item(0)->nodeValue;
		$childTypeName = $typesConnection->getElementsByTagName('child-type')->item(0)->nodeValue;
		$childFieldName = $typesConnection->getElementsByTagName('child-field')->item(0)->nodeValue;
		
		$oParentType = $typesController->getTypeByName($parentTypeName);
		$oChildType = $typesController->getTypeByName($childTypeName);
		
		if ($parentFieldName == 'id') {
			$parentFieldId = 0;
		} else {
			$parentFieldId = $typesController->getTypeByName($parentTypeName)->getFieldByName($parentFieldName)->getId();
		}
		
		$object = new Object($oTypeConnection);
		$object->setValues(array(
			'parent_type_id' => $oParentType->getId(),
			'child_type_id' => $oChildType->getId(),
			'child_rel_field_id' => $oChildType->getFieldByName($childFieldName)->getId(),
			'parent_field_id' => $parentFieldId,
			'connection_type' => $typesConnection->getElementsByTagName('connection-type')->item(0)->nodeValue,
			'alias' => $typesConnection->getElementsByTagName('alias')->item(0)->nodeValue
		));
		
		$object->createNew();
		
		if (isset($this->aVaitConnectedFields[$key])) {
			foreach ($this->aVaitConnectedFields[$key] as $oField) {
				$oField->setValue('connection_id', $object->getId());
				$connectedFieldName = $oField->getAttribute('connected_field_name');
				
				if ($oField->getValue('type_id') == $oChildType->getId()) {
					$connectedFieldId = $oParentType->getFieldByName($connectedFieldName)->getId();
				} else {
					$connectedFieldId = $oChildType->getFieldByName($connectedFieldName)->getId();
				}
				
				$oField->setValue('additional_id', $connectedFieldId);
				$oField->createNew();
			}
		}
	}
	
	private function importImageProfile(DOMElement $imageProfile) {
		$oTypeImgProf = TypesController::getInstance()->getTypeByName('image_profile');
		
		$key = $imageProfile->getAttribute('key');
		
		$object = new Object($oTypeImgProf);
		$object->setValues(array(
			'title' => $imageProfile->getElementsByTagName('title')->item(0)->nodeValue,
			'max_width' => $imageProfile->getElementsByTagName('max-width')->item(0)->nodeValue,
			'max_height' => $imageProfile->getElementsByTagName('max-height')->item(0)->nodeValue,
			'exit_type' => $imageProfile->getElementsByTagName('exit-type')->item(0)->nodeValue,
			'dir' => $imageProfile->getElementsByTagName('dir')->item(0)->nodeValue
		));
		$object->createNew();
		
		if (isset($this->aVaitImagesFields[$key])) {
			foreach ($this->aVaitImagesFields[$key] as $oField) {
				$oField->setValue('additional_id', $object->getId());
				$oField->createNew();
			}
		}
	}
	
	private function importGuide(DOMElement $type) {
		$typesController = TypesController::getInstance();
		
		$oTypeGuide = $typesController->getTypeByName('explay_guide');
		
		$typeName = $type->getAttribute('name');
		
		$oType = $typesController->getTypeByName($typeName);
		
		$sel = new Selection;
		$sel->addType($oTypeGuide);
		$sel->addFilter('type_id', $oType->getId());
		
		$res = $sel->getList();
		
		if (count($res)) {
			$guideId = $res[0][0];
		} else {
			$object = new Object($oTypeGuide);
			$object->setValues(array(
				'type_id' => $oType->getId(),
				'label_field_id' => $oType->getFieldByName($type->getAttribute('label-field'))->getId()
			));
			$object->createNew();
			
			$guideId = $object->getId();
		}
		
		if (isset($this->aVaitGuidesFields[$typeName])) {
			foreach ($this->aVaitGuidesFields[$typeName] as $oField) {
				$oField->setValue('additional_id', $guideId);
				$oField->createNew();
			}
		}
	}
	
}